use std::{
	future::PollFn,
	task::{Context, Poll},
};

use tokio::sync::mpsc;

///消息交换的特征,用于描述两个线程(协程)之间数据的交换对象
///这是使用两个无界队
pub struct MesasgeExchange<TD, FD> {
	pub sender: mpsc::UnboundedSender<TD>,
	pub recver: mpsc::UnboundedReceiver<FD>,
}

impl<TD, FD> MesasgeExchange<TD, FD> {
	#[inline]
	pub fn send(&self, data: TD) -> Result<(), mpsc::error::SendError<TD>> {
		self.sender.send(data)
	}

	#[inline]
	pub fn recv<'a>(
		&'a mut self,
	) -> PollFn<impl FnMut(&'a mut Context<'_>) -> Poll<Option<FD>> + use<'a, TD, FD>> {
		std::future::poll_fn(|cx| self.recver.poll_recv(cx))
	}
}

/// 返回一对消息的收发器...对应两个协程之间的消息发送和接收.
/// 协程两边需要同时两组收发消息的对象.使用此方法得到的两个实例分别交给两边即可
#[inline]
pub fn pair_unbounded_channel<M1, M2>() -> (MesasgeExchange<M1, M2>, MesasgeExchange<M2, M1>) {
	let (tx1, rx1) = mpsc::unbounded_channel::<M1>();
	let (tx2, rx2) = mpsc::unbounded_channel::<M2>();

	(
		MesasgeExchange {
			sender: tx1,
			recver: rx2,
		},
		MesasgeExchange {
			sender: tx2,
			recver: rx1,
		},
	)
}
